namespace com.crownpack.Features.SiteLevel
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    using com.crownpack.Exceptions.SharePointExceptions;
    using com.crownpack.exporttimer;
    using com.crownpack.Extensions.SharePointExtensions;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    using Microsoft.SharePoint.Utilities;

    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>
    [Guid( "8cc2a1eb-115d-4e44-a02b-3298c0ad865d" )]
    public class SiteLevelEventReceiver : SPFeatureReceiver
    {
        #region Fields

        static string _Title;

        #endregion Fields

        #region Properties

        public static Guid ID
        {
            get
            {
                return new Guid( "0b41527f-a140-4f8b-ac95-12c6e95fa294" ); // from feature manifest
            }
        }

        public static string Title
        {
            get
            {
                if ( string.IsNullOrEmpty( _Title ) )
                    _Title = SPFarm.Local.GetFeatureDefinition( ID ).GetTitle( );
                return _Title;
            }
        }

        #endregion Properties

        #region Methods

        public override void FeatureActivated( SPFeatureReceiverProperties properties )
        {
            try
            {
                if ( !( properties.Feature.Parent is SPSite ) )
                {
                    throw new FeatureActivationFailedNotScopedForSiteException( ID, Title, properties.GetWebUrl( ) );
                }

                using ( ExportConfiguration_Definition_SiteLevel o = new ExportConfiguration_Definition_SiteLevel( properties ) )
                    o.Create( );

                using ( ExportConfiguration_Definition_WebLevel o = new ExportConfiguration_Definition_WebLevel( properties ) )
                    o.Create( );

                scheduleTimerJobs( properties );
            }
            catch ( Exception e )
            {
                throw new FeatureActivationException( ID, Title, properties.GetWebUrl( ), e );
            }
        }

        public override void FeatureDeactivating( SPFeatureReceiverProperties properties )
        {
            try
            {
                if ( !( properties.Feature.Parent is SPSite ) )
                {
                    throw new FeatureDeactivationFailedNotScopedForSiteException( ID, Title, properties.GetWebUrl( ) );
                }

                cleanupTimerJobs( properties );

                using ( ExportConfiguration_Definition_WebLevel o = new ExportConfiguration_Definition_WebLevel( properties ) )
                    o.Delete( );

                using ( ExportConfiguration_Definition_SiteLevel o = new ExportConfiguration_Definition_SiteLevel( properties ) )
                    o.Delete( );
            }
            catch ( Exception e )
            {
                throw new FeatureDeactivationException( ID, Title, properties.GetWebUrl( ), e );
            }
        }

        void cleanupTimerJobs( SPFeatureReceiverProperties properties )
        {
            using ( SPSite spSite = properties.GetSite( ) )
            {
                cleanup_FullExportJob( properties );
                cleanup_IncrementalExportJob( properties );
            }
        }

        void cleanup_FullExportJob( SPFeatureReceiverProperties properties )
        {
            SPSecurity.RunWithElevatedPrivileges( delegate( )
            {
                using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
                {
                    foreach ( SPJobDefinition job in spSite.WebApplication.JobDefinitions )
                        if ( job.Name == FullExportJob.JOBNAME )
                        {
                            spSite.AllowUnsafeUpdates = true;
                            try
                            {
                                job.Delete( );
                            }
                            catch
                            {
                                DoNothing( );
                            }
                            break;
                        }
                }
            } );
        }

        void cleanup_IncrementalExportJob( SPFeatureReceiverProperties properties )
        {
            SPSecurity.RunWithElevatedPrivileges( delegate( )
            {
                using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
                {
                    foreach ( SPJobDefinition job in spSite.WebApplication.JobDefinitions )
                        if ( job.Name == IncrementalExportJob.JOBNAME )
                        {
                            spSite.AllowUnsafeUpdates = true;
                            try
                            {
                                job.Delete( );
                            }
                            catch
                            {
                                DoNothing( );
                            }
                            break;
                        }
                }
            } );
        }

        /// <summary>
        /// This method does nothing. It is a placeholder as a reminder that with intent the error is ignored.
        /// </summary>
        void DoNothing( )
        {
        }

        void scheduleTimerJobs( SPFeatureReceiverProperties properties )
        {
            DateTime now = DateTime.Now;
            DateTime begin = new DateTime( now.Year, now.Month, now.Day, 0, 0, 0, 0 );
            DateTime end = begin.AddHours( 3 );

            schedule_FullExportJob( properties, begin, end );

            begin = end.AddHours( 1 );
            end = begin.AddHours( 3 );

            schedule_IncrementalExportJob( properties, begin, end );
        }

        void schedule_FullExportJob( SPFeatureReceiverProperties properties, DateTime begin, DateTime end )
        {
            cleanup_FullExportJob( properties );

            SPSecurity.RunWithElevatedPrivileges( delegate( )
            {
                FullExportJob timerJob = new FullExportJob( FullExportJob.JOBNAME, properties.GetWebApplication( ) );
                SPDailySchedule schedule = new SPDailySchedule( );
                schedule.BeginHour = begin.Hour;
                schedule.BeginMinute = begin.Minute;
                schedule.BeginSecond = begin.Second;
                schedule.EndHour = end.Hour;
                schedule.EndMinute = end.Minute;
                schedule.EndSecond = end.Second;
                timerJob.Schedule = schedule;
                using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
                {
                    spSite.AllowUnsafeUpdates = true;
                    timerJob.Update( true );
                }
            } );
        }

        void schedule_IncrementalExportJob( SPFeatureReceiverProperties properties, DateTime begin, DateTime end )
        {
            cleanup_IncrementalExportJob( properties );

            SPSecurity.RunWithElevatedPrivileges( delegate( )
            {
                IncrementalExportJob timerJob = new IncrementalExportJob( IncrementalExportJob.JOBNAME, properties.GetWebApplication( ) );
                SPDailySchedule schedule = new SPDailySchedule( );
                schedule.BeginHour = begin.Hour;
                schedule.BeginMinute = begin.Minute;
                schedule.BeginSecond = begin.Second;
                schedule.EndHour = end.Hour;
                schedule.EndMinute = end.Minute;
                schedule.EndSecond = end.Second;
                timerJob.Schedule = schedule;
                using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
                {
                    spSite.AllowUnsafeUpdates = true;
                    timerJob.Update( true );
                }
            } );
        }

        #endregion Methods
    }
}